﻿using Microsoft.Extensions.DependencyInjection;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Reflection;
using System.Runtime.Loader;

namespace MES.Core.LoadAssemblys
{
    /// <summary>
    /// dll文件的加载
    /// </summary>
    public class LoadDll
    {
        /// <summary>
        /// 任务实体
        /// </summary>
        public ITask _task;
        public Thread _thread;
        /// <summary>
        /// 核心程序集加载
        /// </summary>
        public AssemblyLoadContext _AssemblyLoadContext { get; set; }
        /// <summary>
        /// 获取程序集
        /// </summary>
        public Assembly _Assembly { get; set; }
        /// <summary>
        /// 文件地址
        /// </summary>
        public string filepath = string.Empty;
        /// <summary>
        /// 指定位置的插件库集合
        /// </summary>
        AssemblyDependencyResolver resolver { get; set; }

        public bool LoadFile(string filepath)
        {
            this.filepath = filepath;
            try
            {
                resolver = new AssemblyDependencyResolver(filepath);
                _AssemblyLoadContext = new AssemblyLoadContext(Guid.NewGuid().ToString("N"), true);
                _AssemblyLoadContext.Resolving += _AssemblyLoadContext_Resolving;

                using (var fs = new FileStream(filepath, FileMode.Open, FileAccess.Read))
                {
                    _Assembly = _AssemblyLoadContext.LoadFromStream(fs);
                    var Modules = _Assembly.Modules;
                    foreach (var item in _Assembly.GetTypes())
                    {
                        if (item.GetInterface("ITask") != null)
                        {
                            _task = (ITask)Activator.CreateInstance(item);
                            break;
                        }
                    }

                    // 成功加载后更新XML并刷新Swagger相关配置
                    UpdateXmlAndRefreshSwagger(_Assembly);
                    return true;
                }
            }
            catch (Exception ex) { Console.WriteLine($"LoadFile:{ex.Message}"); };
            return false;
        }

        private Assembly _AssemblyLoadContext_Resolving(AssemblyLoadContext arg1, AssemblyName arg2)
        {
            Console.WriteLine($"加载{arg2.Name}");
            var path = resolver.ResolveAssemblyToPath(arg2);
            if (!string.IsNullOrEmpty(path))
            {
                using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    return _AssemblyLoadContext.LoadFromStream(fs);
                }
            }
            return null;
        }

        public bool StartTask()
        {
            bool RunState = false;
            try
            {
                if (_task != null)
                {
                    _thread = new Thread(new ThreadStart(_Run));
                    _thread.IsBackground = true;
                    _thread.Start();
                    RunState = true;
                }
            }
            catch (Exception ex) { Console.WriteLine($"StartTask:{ex.Message}"); };
            return RunState;
        }

        private void _Run()
        {
            try
            {
                _task.Run();
            }
            catch (Exception ex) { Console.WriteLine($"_Run 任务中断执行:{ex.Message}"); };
        }

        public bool UnLoad()
        {
            try
            {
                _thread?.Interrupt();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"UnLoad:{ex.Message}");
            }
            finally
            {
                _thread = null;
            }
            _task = null;
            try
            {
                _AssemblyLoadContext?.Unload();
            }
            catch (Exception)
            { }
            finally
            {
                _AssemblyLoadContext = null;
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
            return true;
        }

        // 生成XML文件的方法（简单示意，实际可能需要借助MSBuild等更复杂工具来实现）
        private void GenerateXmlFile(Assembly assembly, string xmlFilePath)
        {
            //更新文件内容
            // 这里假设使用一种简单方式来更新XML文件，比如清空文件内容并重新写入（实际需要完善逻辑来真正提取代码注释
            File.WriteAllText(xmlFilePath, "<?xml version=\"1.0\" encoding=\"utf-8\"?><doc></doc>");

        }

        // 更新XML文件并刷新Swagger配置的方法
        private void UpdateXmlAndRefreshSwagger(Assembly assembly)
        {
            // 生成对应程序集的XML文件
            var xmlFile = $"{assembly.GetName().Name}.xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            GenerateXmlFile(assembly, xmlPath);

            // 获取应用程序的服务提供器（这里假设在合适的启动配置中有正确设置，使得可以获取到SwaggerGenOptions）
            var swaggerGenOptions = new SwaggerGenOptions();
            if (swaggerGenOptions != null)
            {
                // 让Swagger重新包含更新后的XML文件注释
                swaggerGenOptions.IncludeXmlComments(xmlPath, true); // true : 显示控制器层注释
                swaggerGenOptions.OrderActionsBy(o => o.RelativePath); // 对action的名称进行排序，如果有多个，就可以看见效果了。
            }
        }

    }

    public class PrintStr : ITask
    {
        public void Run()
        {
            LoadDll loadDll = new LoadDll();
            loadDll.LoadFile($@"{AppDomain.CurrentDomain.SetupInformation.ApplicationBase}\MES.Core.dll");
            loadDll.LoadFile($@"{AppDomain.CurrentDomain.SetupInformation.ApplicationBase}\MES.API.dll");
            loadDll.LoadFile($@"{AppDomain.CurrentDomain.SetupInformation.ApplicationBase}\MES.Model.dll");
            loadDll.LoadFile($@"{AppDomain.CurrentDomain.SetupInformation.ApplicationBase}\MES.Service.dll");
            Console.WriteLine("程序重新启动");
        }

    }
}
